Snowflakeのユーザーステージ経由でファイルをロードしてみた
こんにちは!DA(データアナリティクス)事業本部 インテグレーション部の大高です。
Snowflakeには「ステージ」というSnowflakeのテーブルにファイルからデータをロードする際に、そのファイルを置く場所があります。
「ステージ」の種類としては大きく2つあり、Snowflake内部にある「内部ステージ」と、各種クラウド上(Amazon S3, Google Cloud Storage, Microsoft Azure)に存在するファイルとの架け橋になる「外部ステージ」があります。
今回はこのうちの「内部ステージ」における「ユーザーステージ」を利用して、ファイルデータをテーブルへロードしてみました。
内部ステージについての概要は以下の記事でもまとめています。
「やりたいこと」と「事前準備」
ローカルPCにあるCSVファイルを、「ユーザーステージ」を経由してSnowflake上のテーブルにロードしてみたいと思います。
今回利用するファイルは以下のようなCSVファイルとします。
id,name,age 1,Aruto Hiden,22 2,Izu, 3,Isamu Fuwa,27 4,Yua Yaiba,24 5,Gai Amatsu,45 6,Horobi, 7,Naki, 8,Jin, 9,Ikazuchi,
Snowflakeには事前にデータベースとテーブルを用意しておきます。
USE ROLE OOTAKA_SANDBOX_ROLE; -- ROLEは事前作成済みのものを利用します CREATE DATABASE OOTAKA_SANDBOX_DB; USE DATABASE OOTAKA_SANDBOX_DB; CREATE TABLE public.users( id INTEGER, name STRING, age INTEGER );
これらを利用して、進めていきます。
「ユーザーステージ」のおさらい
ユーザーステージは「ユーザー」に紐づくステージで、各ユーザーにデフォルトで割り当てられています。ユーザーに紐づくのでファイルへのアクセスは自分のみとなり、ファイルは各テーブルにCOPYすることができます。 また、対象テーブルへのINSERT権限が必要となります。
これを踏まえると、ステージは既にできており、テーブルも先程作成したテーブルにINSERT権限がある状態なので問題ないですね。
ファイルのステージング
では、準備ができたのでまずはファイルをステージング(アップロード)します。ファイルのステージングは下記を参考に進めます。
ステージングは以下のようにPUT
コマンドを使って、ローカルファイルをユーザーステージ上の指定の場所にステージングできるようです。
put file:///data/data.csv @~/staged;
今回はSnowSQLを使ってPUT
してみます。まずはステージングするファイルの確認から。
$ cat /tmp/users.csv id,name,age 1,Aruto Hiden,22 2,Izu, 3,Isamu Fuwa,27 4,Yua Yaiba,24 5,Gai Amatsu,45 6,Horobi, 7,Naki, 8,Jin, 9,Ikazuchi,
問題ないですね。SnowSQLを起動してこれをステージングしてみます。ファイルはユーザーステージのusers
ディレクトリ配下にステージングします。
$ snowsql * SnowSQL * v1.2.7 Type SQL statements or !help foo_bar#(no warehouse)@(no database).(no schema)>put file:///tmp/users.csv @~/users; users.csv_c.gz(0.00MB): [##########] 100.00% Done (0.097s, 0.00MB/s). +-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------+ | source | target | source_size | target_size | source_compression | target_compression | status | message | |-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------| | users.csv | users.csv.gz | 130 | 147 | NONE | GZIP | UPLOADED | | +-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------+ 1 Row(s) produced. Time Elapsed: 1.240s
ステージングされました!デフォルトでGZIP圧縮も行ってくれているのが分かります。念のため、LIST
コマンドでユーザーステージを確認してみます。
foo_bar#(no warehouse)@(no database).(no schema)>list @~/users; +--------------------+------+----------------------------------+------------------------------+ | name | size | md5 | last_modified | |--------------------+------+----------------------------------+------------------------------| | users/users.csv.gz | 160 | 0a75b2ffe08fad9f527f90f4729633ec | Thu, 9 Jul 2020 01:16:06 GMT | +--------------------+------+----------------------------------+------------------------------+ 1 Row(s) produced. Time Elapsed: 0.147s
ちゃんとusers
配下にusers.csv.gz
ファイルがありますね。
データのコピー
ステージングが出来たので、ファイルからテーブルへデータをコピーしてみます。コピーについてはこちらを参考に実施します。
コピーは以下のようにCOPY
コマンドを使って、ユーザーステージ上のファイルを、指定したテーブルとファイルフォーマットでコピーできるようです。
copy into mytable from @~/staged file_format = (format_name = 'my_csv_format');
ではやってみます。まずは、ウェアハウス、データベースを指定しておきます。
foo_bar#(no warehouse)@(no database).(no schema)>USE WAREHOUSE X_SMALL_WH; +----------------------------------+ | status | |----------------------------------| | Statement executed successfully. | +----------------------------------+ 1 Row(s) produced. Time Elapsed: 0.591s foo_bar#X_SMALL_WH@(no database).(no schema)>USE DATABASE OOTAKA_SANDBOX_DB; +----------------------------------+ | status | |----------------------------------| | Statement executed successfully. | +----------------------------------+ 1 Row(s) produced. Time Elapsed: 0.134s
テーブルの中身が空なのも確認しておきましょう。
foo_bar#X_SMALL_WH@OOTAKA_SANDBOX_DB.PUBLIC>SELECT * FROM USERS; +----+------+-----+ | ID | NAME | AGE | |----+------+-----| +----+------+-----+ 0 Row(s) produced. Time Elapsed: 0.168s
空ですね。ではCOPY
コマンドを使ってコピーしてみます。今回、ファイルフォーマットのオブジェクトは作成していないので、format_name
で指定はせずに、明示的に指定してみます。
foo_bar#X_SMALL_WH@OOTAKA_SANDBOX_DB.PUBLIC>copy into users from @~/users file_format = (type = csv field_delimiter = ',' skip_header = 1); +--------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------+ | file | status | rows_parsed | rows_loaded | error_limit | errors_seen | first_error | first_error_line | first_error_character | first_error_column_name | |--------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------| | users/users.csv.gz | LOADED | 9 | 9 | 1 | 0 | NULL | NULL | NULL | NULL | +--------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------+ 1 Row(s) produced. Time Elapsed: 1.171s
成功しました!テーブルを確認してみます。
foo_bar#X_SMALL_WH@OOTAKA_SANDBOX_DB.PUBLIC>SELECT * FROM USERS; +----+-------------+-----+ | ID | NAME | AGE | |----+-------------+-----| | 1 | Aruto Hiden | 22 | | 2 | Izu | NULL | | 3 | Isamu Fuwa | 27 | | 4 | Yua Yaiba | 24 | | 5 | Gai Amatsu | 45 | | 6 | Horobi | NULL | | 7 | Naki | NULL | | 8 | Jin | NULL | | 9 | Ikazuchi | NULL | +----+-------------+-----+ 9 Row(s) produced. Time Elapsed: 0.280s
想定通りコピーされました!
ステージングしたファイルの削除
最後に、ステージングしたファイルをREMOVE
コマンドで削除しておきます。
foo_bar#X_SMALL_WH@OOTAKA_SANDBOX_DB.PUBLIC>remove @~/users; +--------------------+---------+ | name | result | |--------------------+---------| | users/users.csv.gz | removed | +--------------------+---------+ 1 Row(s) produced. Time Elapsed: 0.644s
削除できました。一応確認してみます。
foo_bar#X_SMALL_WH@OOTAKA_SANDBOX_DB.PUBLIC>list @~/users; +------+------+-----+---------------+ | name | size | md5 | last_modified | |------+------+-----+---------------| +------+------+-----+---------------+ 0 Row(s) produced. Time Elapsed: 0.562s
問題なく消えていますね!
まとめ
以上、ユーザーステージ経由でファイルをロードしてみました。ユーザーステージであれば、デフォルトで自分用に用意されているのでお手軽に利用できそうですね。
どなたかのお役に立てば幸いです。それでは!